{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13c3d1ea",
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
   "outputs": [],
   "source": [
    "# /// script\n",
    "# requires-python = \">=3.12\"\n",
    "# dependencies = [\n",
    "#     \"geopandas\",\n",
    "#     \"lonboard\",\n",
    "#     \"matplotlib\",\n",
    "#     \"palettable\",\n",
    "#     \"pyarrow\",\n",
    "#     \"pyogrio\",\n",
    "# ]\n",
    "# ///"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68b4877a-d595-47b4-988f-b470eb4251e5",
   "metadata": {},
   "source": [
    "# North America Roads\n",
    "\n",
    "This example uses data from [Natural Earth](https://www.naturalearthdata.com/) to plot the road network in North America. Refer to the [data documentation](https://www.naturalearthdata.com/downloads/10m-cultural-vectors/roads/) for more information about this dataset.\n",
    "\n",
    "You can view a [hosted version of this notebook on Notebook Sharing Space](https://notebooksharing.space/view/8fcb718843e480c7a3bb0065155466103984f41225d66aa9b25790363a346531#displayOptions=) (6MB download).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81ac8d53",
   "metadata": {},
   "source": [
    "## Dependencies\n",
    "\n",
    "Install [`uv`](https://docs.astral.sh/uv) and then launch this notebook with:\n",
    "\n",
    "```\n",
    "uvx juv run examples/north-america-roads.ipynb\n",
    "```\n",
    "\n",
    "(The `uvx` command is included when installing `uv`).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d404b794-1456-42ee-9161-c50b70c831ef",
   "metadata": {},
   "source": [
    "## Imports\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "51abc06e-0d06-40ef-aea6-19130e88bce3",
   "metadata": {},
   "outputs": [],
   "source": [
    "import geopandas as gpd\n",
    "import palettable.colorbrewer.diverging\n",
    "\n",
    "from lonboard import Map, PathLayer\n",
    "from lonboard.colormap import apply_continuous_cmap"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d4ddc6c3-7538-44cd-a082-912aa5aef1cc",
   "metadata": {},
   "source": [
    "The \"public\" URL for this dataset from the Natural Earth website is\n",
    "\n",
    "```\n",
    "https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_roads_north_america.zip\n",
    "```\n",
    "\n",
    "That doesn't appear to work directly inside a notebook, so we'll use the URL the above redirects to:\n",
    "\n",
    "```\n",
    "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_roads_north_america.zip\n",
    "```\n",
    "\n",
    "It's possible this \"private\" URL will change in the future.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce868022-f3e4-4db5-83d7-af65b5e2f959",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = \"https://naciscdn.org/naturalearth/10m/cultural/ne_10m_roads_north_america.zip\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d77aa88-6d94-4eac-a5c7-e52efcc93930",
   "metadata": {},
   "source": [
    "We'll use GeoPandas to fetch this data (45MB) over the internet and load it into a `GeoDataFrame`. This uses the [`pyogrio` engine](https://geopandas.org/en/stable/docs/reference/api/geopandas.read_file.html), which is faster. Ensure you have [`pyogrio`](https://github.com/geopandas/pyogrio) installed.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c97da98c-cce8-4f66-b598-59eef05367de",
   "metadata": {},
   "outputs": [],
   "source": [
    "gdf = gpd.read_file(url, engine=\"pyogrio\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4a9b9a1-9d78-42a3-be88-60ac550a84de",
   "metadata": {},
   "source": [
    "This dataframe has a variety of attributes, plus a geometry column with a `LineString` type.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "14d60ee4-4006-48b3-8ddb-52e3ae6002da",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "gdf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d1caaa7-7d99-451c-a385-6aac276fd43c",
   "metadata": {},
   "source": [
    "To ensure that this demo is snappy on most computers, we'll filter to only the contiguous U.S. If you're on a recent computer, feel free to comment out this line.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0e690480-25fa-4f12-aba6-3477a0f86a27",
   "metadata": {},
   "outputs": [],
   "source": [
    "gdf = gdf[gdf[\"state\"] == \"California\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11f005c2-2cac-47d7-aec4-cd00057646f8",
   "metadata": {},
   "source": [
    "To render `LineString` data, first create a `PathLayer` and then add it to a `Map` object.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "053eb025-6ddd-46c1-8159-061b9eb7c09e",
   "metadata": {},
   "outputs": [],
   "source": [
    "layer = PathLayer.from_geopandas(gdf, width_min_pixels=0.8)\n",
    "map_ = Map(layer)\n",
    "map_"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6bdfd6d-2689-42f6-a538-8f833c6d539a",
   "metadata": {},
   "source": [
    "We can look at the [documentation for `PathLayer`](https://developmentseed.org/lonboard/latest/api/layers/path-layer/) to see what other rendering options it allows. Let's set the path color to something other than black:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "75f67a77-062a-4043-9454-5b2b97b52288",
   "metadata": {},
   "outputs": [],
   "source": [
    "layer.get_color = [200, 0, 200]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bac0f0b-7129-476c-8ea0-51c1bede0f4d",
   "metadata": {},
   "source": [
    "Ok, so we can see the data! That's great! But let's customize the rendering based on an attribute!\n",
    "\n",
    "The `scalerank` column tells how important the road is in the road network. Let's see what the distribution of values is for this column:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5c33098b-0348-4b07-9ae4-5c56d5d50723",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "gdf[\"scalerank\"].value_counts().sort_index()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "667e990e-5424-47fe-9847-c8be297cf425",
   "metadata": {},
   "source": [
    "Ok, so the values range from `3` to `12`. To assign a colormap to this column, we need \"normalized\" values that span between 0 and 1:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c7d26678-418e-48f8-827d-050d9f2df1dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "normalized_scale_rank = (gdf[\"scalerank\"] - 3) / 9"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00f628bc-34ff-4b95-9998-27e0d66b1b61",
   "metadata": {},
   "source": [
    "The values of this array now range from 0 to 1:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "12be09c8-0857-44d8-ad14-69b4c7277fbc",
   "metadata": {},
   "outputs": [],
   "source": [
    "normalized_scale_rank.min(), normalized_scale_rank.max()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a5c4f17e-9465-44ee-b54e-26a351574a29",
   "metadata": {},
   "source": [
    "Let's select a colormap to apply to this data:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1df9d2c9-6f10-49e6-aa4f-6718f3d2f765",
   "metadata": {},
   "outputs": [],
   "source": [
    "cmap = palettable.colorbrewer.diverging.PuOr_10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6e0f48ab-0cbe-4ce9-b804-9a1a3330ff9f",
   "metadata": {},
   "outputs": [],
   "source": [
    "cmap.mpl_colormap"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "74d9d749-4222-4aa8-bf12-ded79187a616",
   "metadata": {},
   "source": [
    "Now we'll use `apply_continuous_cmap` onto this array to generate colors for our data. Just set this new array onto the existing layer, and you'll see the map update with the new colors!\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7288a2d7-3190-4f9e-b29e-bbba32109024",
   "metadata": {},
   "outputs": [],
   "source": [
    "layer.get_color = apply_continuous_cmap(\n",
    "    normalized_scale_rank,\n",
    "    palettable.colorbrewer.diverging.PuOr_10,\n",
    "    alpha=0.8,\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  },
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "state": {},
    "version_major": 2,
    "version_minor": 0
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
